/**
 * @fileOverview Player Worker
 *
 * @author Mikhail Davydov
 *
 */

/**#nocode+*/
(function (global) {
/**#nocode-*/

    /**
     * Callbacks
     *
     * @namespace Callbacks
     */
    var Callbacks = {
        /**
         * Main callback in must return action via Player.post
         *
         * <pre>
         * State example:
         * {
         *  "fow":[ // player's field of view: array of items (man or wall)
         *      {"object":{"name":0},"x":2,"y":3}, // man item (self or enemy, depend on name)
         *      {"object":0,"x":0,"y":3}, // wall item
         *      {"object":0,"x":0,"y":2}, // wall item
         *      {"object":0,"x":0,"y":4}  // wall item
         *      ],
         *  "apLeft":1, // action points left
         *  "player": // current player info
         *      {
         *          "x":2, // x
         *          "y":3, // y
         *          "name":0, // name
         *          "direction":3, // direction
         *          "health":10, // hp
         *          "shield":2 // sh
         *      }
         * }
         *
         * Return example:
         * Player.post({
         *     action: 'move', // action
         *     options: {x: 2, y: 4},
         *     direction: ~~(Math.random() * 5) // random direction
         * });
         * </pre>
         *
         * @param {Object} state
         * @returns {Object}
         */
        callback: function (state) {

            // its own id
            var id = state.player.name,
                target,
                i, c, ok = false, fow = [];

            // looking for enemy in fow
            for (i = 0, c = state.fow.length; i < c; i += 1) {

                // push fow elements to 2d array, required for movements
                if (!fow[state.fow[i].y]) {
                    fow[state.fow[i].y] = [];
                }
                fow[state.fow[i].y][state.fow[i].x] = state.fow[i].object;

                if (typeof state.fow[i].object === 'object' && state.fow[i].object.name !== id) {
                    // found!
                    target = {
                        x: state.fow[i].x,
                        y: state.fow[i].y
                    };
                }
            }
            if (target) { //  target - shoot!
                Player.post({
                    action: 'shoot', // shoot action
                    options: target, // enemy x y
                    direction: state.player.direction // do not change direction
                });
            } else { // no target - seeking for target
                // make random moves
                if (Math.random() > 0.5) { // move to x
                    while (!ok) { // check if cell not occupied
                        target = {
                            x: state.player.x + (~~(Math.random() * 3) - 1),
                            y: state.player.y
                        };
                        if (typeof fow[target.y] === 'undefined' || typeof fow[target.y][target.x] === 'undefined' ) {
                            ok = true; // cell is free
                        }
                    }
                } else { // or move to y
                    while (!ok) { // check if cell not occupied
                        target = {
                            x: state.player.x,
                            y: state.player.y + (~~(Math.random() * 3) - 1)
                        };
                        if (typeof fow[target.y] === 'undefined' || typeof fow[target.y][target.x] === 'undefined' ) {
                            ok = true; // cell is free
                        }
                    }
                }
                Player.post({
                    action: 'move', // move action
                    options: target,
                    direction: ~~(Math.random() * 5) // random direction
                });
            }
        },

        /**
         * <pre>
         * param: {damage: damage, x: target.x, y: target.y, name: target.name}
         * </pre>
         * @event
         *
         * @param {Object} param
         */
        onHit: function (param) {

        },

        /**
         * <pre>
         * param: {damage: damage, health: target.health, shield: target.shield, x: player.x, y: player.y, name: player.name}
         * </pre>
         * @event
         *
         * @param {Object} param
         */
        onDamage: function (param) {

        },

        /**
         * <pre>
         * param: {name: target.name}
         * </pre>
         * @event
         *
         * @param {Object} param
         */
        onKill: function (param) {

        },
        /**
         * @event
         *
         */
        onDead: function () {

        },

        /**
         * <pre>
         * param: {x: x, y: y}
         * </pre>
         * @event
         *
         * @param {Object} param
         */
        onAfterMove: function (param) {

        },

        /**
         * <pre>
         * param: {action: action, actionCost: actionCost}
         * </pre>
         * @event
         *
         * @param {Object} param
         */
        onFailAction: function (param) {

        },
        /**
         * <pre>
         * amount: 1
         * </pre>
         * @event
         *
         * @param {Number} amount
         */
        onShieldRegen: function (amount) {

        }
    };

    /**
     * Player
     * @namespace Player
     */
    var Player = {
        post: function (data) {
            global.postMessage(JSON.stringify(data));
        }
    };

    /**
     * Message listener
     */
    global.onmessage = function (e) {
        var data = JSON.parse(e.data);
        if (data.call && typeof Callbacks[data.call] === 'function') {
            Callbacks[data.call](data.arguments);
        }
    };

/**#nocode+*/
}(this));
/**#nocode-*/